package org.swift.commons.xml.vtd;

import java.io.File;
import java.util.Map;

import org.swift.commons.xml.Match;
import org.swift.commons.xml.ValueMatch;

import com.ximpleware.extended.AutoPilotHuge;
import com.ximpleware.extended.NavExceptionHuge;
import com.ximpleware.extended.Position;
import com.ximpleware.extended.VTDGenHuge;
import com.ximpleware.extended.VTDNavHuge;

public class FileNavigator implements Navigator {
	private final VTDGenHuge gen;
	private final VTDNavHuge nav;
	private final File file;
	
	public FileNavigator(File file) {
		this.gen = new VTDGenHuge();
		final boolean namespaceAware= true;
		gen.parseFile(file.getAbsolutePath(), namespaceAware, VTDGenHuge.MEM_MAPPED);
		this.file = file;		
		this.nav = gen.getNav();
	}

	@Override
	public int getAttrVal(String string) throws NavigationException {
		try {
			return this.nav.getAttrVal(string);
		} catch (NavExceptionHuge e) {
			throw new NavigationException(e);
		}
	}

	@Override
	public AutomaticPilot getAutomaticPilot() {
		return new FileAutomaticPilot(
				new AutoPilotHuge(this.nav));
	}
	
	@Override
	public int getText() {
		return nav.getText();
	}

	@Override
	public int getTokenType(int index) {
		return nav.getTokenType(index);
	}

	@Override
	public String toString(int index) throws NavigationException {
		try {
			return nav.toString(index);
		} catch (NavExceptionHuge e) {
			throw new NavigationException(e);
		}
	}

	@Override
	public Match matchAt(int index, Map<String, String> namespaces) throws NavigationException {
		int type = nav.getTokenType(index);
		try {
			switch (type) {
				case VTDNavHuge.TOKEN_STARTING_TAG :		
					Position location = nav.getElementFragment();					
					return new IndexedMatch(this.file, location.getOffset(), (int)location.getLength(), namespaces);
				case VTDNavHuge.TOKEN_ATTR_NAME :
					return new ValueMatch(
							nav.toString( 
							nav.getAttrVal( //index value to attribute
									nav.toString(index))));				
								
				case VTDNavHuge.TOKEN_CHARACTER_DATA :
				case VTDNavHuge.TOKEN_CDATA_VAL :					
						return new ValueMatch(nav.toString(nav.getText()));
			}
		} catch (NavExceptionHuge e) {
			throw new NavigationException(e);
		} 
		throw new RuntimeException("Invalid type returned: " + type);
	}

	
}
